#include "parameters.h"

// computing model
//eComputingModel gComputingModel = RENDER_SINGLE_SIMULATED_COLOR;
//eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL_SIMULATED;
//eComputingModel gComputingModel = RECONSTRUCT_SINGLE_SIMULATED_COLOR;
//eComputingModel gComputingModel = RENDER_SINGLE_SIMULATED_RESULT_COLOR;


//eComputingModel gComputingModel = RENDER_SINGLE_SIMULATED_COLOR_TEMPERATURE;
//eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE;
//eComputingModel gComputingModel = RECONSTRUCT_SINGLE_SIMULATED_COLOR_TEMPERATURE;

eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE_GPU_OCTREE_RESIZE;
int Model_type = 0;

//eComputingModel gComputingModel = ALGEBRAIC_RECONSTRUCTION_SINGLE_SIMULATED;

//eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL;
//eComputingModel gComputingModel = RECONSTRUCT_SINGLE_CAPTURED_COLOR;
//eComputingModel gComputingModel = RENDER_SINGLE_CAPTURED_RESULT_COLOR;

//eComputingModel gComputingModel = GENERATE_SMOKE_VISUAL_HULL;
//eComputingModel gComputingModel = RECONSTRUCT_SMOKE;
//eComputingModel gComputingModel = RENDER_SMOKE_RESULT;

//eComputingModel gComputingModel = RENDER_SINGLE_SIMULATED_TEMPERATURE;
//eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL_SIMULATED_TEMPERATURE;
//eComputingModel gComputingModel = RECONSTRUCT_SINGLE_SIMULATED_TEMPERATURE; 
//eComputingModel gComputingModel = RENDER_SINGLE_SIMULATED_RESULT_TEMPERATURE;

//eComputingModel gComputingModel = GENERATE_VISUAL_HULL_MIXING_FLUID; 
//eComputingModel gComputingModel = RECONSTRUCT_MIXING_FLUID; 


//eComputingModel gComputingModel = RENDER_CT_IMAGE;
//eComputingModel gComputingModel = GENERATE_CT_VISUAL_HULL;
//eComputingModel gComputingModel = RECONSTRUCT_CT;


//uint gWidth = 220, gHeight = 270;
//const int gcNumberCamera = 4; 
//int gIdCurrentCamera = 0;
//int s = 160;
//cudaExtent gVolumeExtent = make_cudaExtent(s, s, s);
//cudaExtent gVolumeExtent = make_cudaExtent(128, 128, 128);
//eComputingModel gComputingModel = GENERATE_SINGLE_VISUAL_HULL;
//eComputingModel gComputingModel = RECONSTRUCT_SINGLE_CAPTURED_TEMPERATURE;
//eComputingModel gComputingModel = RENDER_SINGLE_CAPTURED_RESULT_TEMPERATURE; 


//eComputingModel gComputingModel = RENDER_MULTIPLE_SMOKE;

// rgb channels
int gChannel = 0;



#if 0 
// for captured data
// camera #


// for green and pink flame
//const int gcNumberCamera = 9;
// for yellow flame
const int gcNumberCamera = 16;

int gIdCurrentCamera = 0;

// sampling configuration
int gSamplingMaxSteps = 50000;
float gSamplingStep = 1.5;
uint gWidth = 1280, gHeight = 720;
//cudaExtent gVolumeExtent = make_cudaExtent(512, 512, 512);
//cudaExtent gVolumeExtent = make_cudaExtent(256, 256, 256);
cudaExtent gVolumeExtent = make_cudaExtent(128, 128, 128);
#else
// for simulated data
// camera #


//const int gcNumberCamera = 4; 
//int gIdCurrentCamera = 0;
//
//// sampling configuration
//int gSamplingMaxSteps = 50000;
//float gSamplingStep = 0.01;
//
////uint gWidth = 128, gHeight = 128;
////cudaExtent gVolumeExtent = make_cudaExtent(128, 128, 128);
////cudaExtent gVolumeExtent = make_cudaExtent(256, 256, 256);
////uint gWidth = 640, gHeight = 480;
////cudaExtent gVolumeExtent = make_cudaExtent(128, 128, 128);
//uint gWidth = 200, gHeight = 310;
////cudaExtent gVolumeExtent = make_cudaExtent(200, 200, 310);
////uint gWidth = 640, gHeight = 480;
////cudaExtent gVolumeExtent = make_cudaExtent(640, 640, 480);
////uint gWidth = 220, gHeight = 270;
////cudaExtent gVolumeExtent = make_cudaExtent(200, 200, 300);
//int s = 128;
//cudaExtent gVolumeExtent = make_cudaExtent(s, s, s);

//// for smoke
//uint gWidth = 434, gHeight = 342;
////int s = 64;
//int s = 128;
//cudaExtent gVolumeExtent = make_cudaExtent(s, s, s);


// for other ct data
const int gcNumberCamera = 16;
int gIdCurrentCamera = 0;

// sampling configuration
int gSamplingMaxSteps = 5000;
float gSamplingStep = 0.01;
uint gWidth = 640, gHeight = 480;
//uint gWidth = 400, gHeight = 300;

int s = 9;
uint3 gridSizeLog2 = make_uint3(s, s, s);
cudaExtent gVolumeExtent = make_cudaExtent(pow(2, s), pow(2, s), pow(2, s));

#endif

const char* gCTData = "data/other/lobster.raw.gz";

const int gcNumberFrame = 46;
unsigned int gIdCurrentFrame = 1;
unsigned long gIteration = 0;

// Define the files that are to be save and the reference images for validation
const char *gOriginal[] =
{
	"volume.ppm",
	NULL
};

const char *gReference[] =
{
	"ref_volume.ppm",
	NULL
};

const char *gSDKsample = "CUDA 3D Volume Render";

//const char *volumeFilename = "data/temperature_float128x128x128.data";
const char *gVolumeFilename = "data/frame.data";
size_t gVolumeSize;



float gMinGreenIntensity = 0.f;
float gMaxGreenIntensity = 0.f;

//char *volumeFilename = "mrt16_angio.raw";
//cudaExtent volumeSize = make_cudaExtent(416, 512, 112);
//typedef unsigned short VolumeType;

dim3 gBlockSize;
dim3 gGridSize;

float3 gViewRotation;
float3 gViewTranslation = make_float3(0.0, 0.0, -5.0f);
//float3 gViewTranslation = make_float3(0.0, 0.0, 0.0f);
float gInvViewMatrix[12];
GLfloat  gNearFar[24];

float gDensity = 0.05f;
float gBrightness = 1.0f;
//float gDensity = 0.1f;
//float gBrightness = 2.5f;
float gTransferOffset = 0.0f;
float gTransferScale = 1.0f;
bool gLinearFiltering = true;

GLuint g_pbo = 0;     // OpenGL pixel buffer object
GLuint g_tex = 0;     // OpenGL texture object
struct cudaGraphicsResource *g_cuda_pbo_resource; // CUDA Graphics Resource (to transfer PBO)

StopWatchInterface *gTimer = 0;

// Auto-Verification Code
const int gFrameCheckNumber = 2;
int gFpsCount = 0;        // FPS count for averaging
int gFpsLimit = 1;        // FPS limit for sampling
int gIndex = 0;
unsigned int gFrameCount = 0;

int *pArgc;
char **pArgv;

int gButtonOx, gButtonOy;
int gButtonState = 0;


float3 gBoxMin = make_float3(-1.0f, -1.0f, -1.0f);
float3 gBoxMax = make_float3(1.0f, 1.0f, 1.0f);
float gVoxelLength = 1.f;


// perspective parameters
float* g_array_perspective_fov;
float* g_array_perspective_eye_x;
float* g_array_perspective_eye_y;
float* g_array_perspective_eye_z;
float* g_array_perspective_center_x;
float* g_array_perspective_center_y;
float* g_array_perspective_center_z;
float* g_array_perspective_up_x;
float* g_array_perspective_up_y;
float* g_array_perspective_up_z;

float g_perspective_fov = 0.f;
float g_perspective_eye_x = 0.f;
float g_perspective_eye_y = 0.f;
float g_perspective_eye_z = 0.f;
float g_perspective_center_x = 0.f;
float g_perspective_center_y = 0.f;
float g_perspective_center_z = 0.f;
float g_perspective_up_x = 0.f;
float g_perspective_up_y = 0.f;
float g_perspective_up_z = 0.f;


ResizeImage *gResizeImageData_octree[20];
extrinsic_parameters* extrinsic_par;
extrinsic_parameters* d_extrinsic_par;
view_box visualHullBox;
Octree *visual_hull_Octrees[100];
uint visual_hull_length[100];
//double bounding_box[3][2] = {{-0.073568, 0.028855}, { 0.021728, 0.181892}, { -0.012445, 0.062736 }};
double bounding_box[3][2] = { { -0.061897, 0.010897},{ -0.018874, 0.068227},{ -0.057845, 0.015495 } };


// filename
const char* extrinsicParametersFilename = "data/simulated/single/color_temperature/dinoSR_par.txt";
const char* gBoundingBoxFilename = "data/reconstruction/voxel_info.txt";
const char* gMixingFluidBoundingBoxFilename = "data/paper2012/voxel_info.txt";
const char* gPerspectiveFilename = "data/calibration/output/projection_parameter.txt";
const char* gCameraParaMixingFluidFilename = "data/paper2012/projection_parameter.txt";
const char* gVisualHullSimulatedImageFilename = "data/simulated/single/visual_hull_img_name.txt";
const char* gVisualHullSimulatedColorTemperatureImageFilename = "data/simulated/single/color_temperature/visual_hull_img_name.txt";
const char* gVisualHullSimulatedTemperatureImageFilename = "data/simulated/temperature/visual_hull_img_name.txt";
const char* gVisualHullTagSmulatedFilename = "data/simulated/single/visual_hull.txt";
const char* gVisualHullTagSmulatedColorTemperatureFilename = "data/simulated/single/color_temperature/visual_hull.txt";
const char* gVisualHullTagSmulatedTemperatureFilename = "data/simulated/temperature/visual_hull.txt";
const char* gVisualHullImageFilename = "data/calibration/output/visual_hull_img_name.txt";
const char* gVisualHullMixingFluidImageFilename = "data/paper2012/input_image/image_name.txt";
const char* gVisualHullSmokeImageFilename = "data/smoke/visual_hull_img_name.txt";
const char* gVisualHullTagFilename = "data/reconstruction/single_frame/visual_hull.txt";
const char* gVisualHullMixingFluidTagFilename = "data/paper2012/visual_hull.txt";
const char* gVisualHullTagSmokeFilename = "data/smoke/visual_hull.txt";
const char* gSingleSimulatedTemperatureFilename = "data/simulated/single/frame_30.data";
const char* gSimulatedCameraParameterFilename = "data/simulated/sim_camera_param_zlarge.txt";
const char* gSmokeCameraParameterFilename = "data/smoke/camera_param.txt";
const char* gCTCameraParamFilename = "data/other/camera_param.txt";


// for evaluation
//const char* gSimulatedCameraParameterFilename = "data/simulated/sim_camera_param_zlarge_evaluation.txt";

const char* gCapturedSingleResultPath = "data/reconstruction/single_frame/result/";
const char* gSmokeResultPath = "data/smoke/result/";


const char* gCapturedResultRedFilename = "data/reconstruction/single_frame/result/red.data";
const char* gCapturedResultGreenFilename = "data/reconstruction/single_frame/result/green.data";
const char* gCapturedResultBlueFilename = "data/reconstruction/single_frame/result/blue.data";

const char* gSimulatedRedFilename = "data/simulated/single/red.data";
const char* gSimulatedGreenFilename = "data/simulated/single/green.data";
const char* gSimulatedBlueFilename = "data/simulated/single/blue.data";
const char* gSimulatedResultRedFilename = "data/simulated/single/result/red.data";
const char* gSimulatedResultGreenFilename = "data/simulated/single/result/green.data";
const char* gSimulatedResultBlueFilename = "data/simulated/single/result/blue.data";
const char* gSimulatedImageNamePrefix = "data/simulated/single/input_image/view_";
const char* gCTImageNamePrefix = "data/other/input_image/view_";
const char* gSimulatedImageNameColorTemperaturePrefix = "data/simulated/single/color_temperature/input_image/view_";
const char* gSimulatedResultImageNamePrefix = "data/simulated/single/result/view_";
const char* gCapturedResultImageNamePrefix = "data/reconstruction/single_frame/result/view_";
const char* gSimulatedVolumeDataFilenamePrefix = "data/simulated/single/result/";
const char* gSimulatedVolumeColorTemperatureFilenamePrefix = "data/simulated/single/color_temperature/result/";
const char* gSimulatedVolumeTemperatureFilenamePrefix = "data/simulated/temperature/result/";
const char* gSmokeResultImageNamePrefix = "data/smoke/result/view_";

const char* gSimulatedTemperatureImageNamePrefix = "data/simulated/temperature/input/view_";
const char* gSimulatedTemperatureResultImageNamePrefix = "data/simulated/temperature/result/view_";
const char* gSimulatedTemperatureResultVolumeDataFilename = "data/simulated/temperature/result/temperature.data";


const char* gCapturedTemperatureResultImageNamePrefix = "data/reconstruction/single_frame/temperature/result/view_";
const char* gCapturedTemperatureResultVolumeDataFilename = "data/reconstruction/single_frame/temperature/result/temperature.data";

const char* gMultipleSmokeVolumeDataPrefix = "data/smoke/multiple/volume_data/frame_";
//const char* gMultipleSmokeVolumeDataPrefix = "data/smoke/multiple/volume_data/data_";
const char* gMultipleSmokeImagePrefix = "data/smoke/multiple/image/newframe_";

// source image information
char* gSourceImageData = 0;
int gSourceImageWidthStep;
int gSourceImageNChannels;
int* integrogram;
int* d_source_imtegrogram = nullptr;



// visual hull tag
uchar* gVisualHullVertexTag = nullptr; // points around a voxel
uchar* gVisualHullTag = nullptr;
VisualHullType* gCustomVisualHullTag = nullptr;


// color reconstruction
float* gVolumeColor = nullptr;

// for evaluation
float* gSrcVolumeColor = nullptr;


uint* gOutput = nullptr;

char* d_source_image_data = nullptr;

float* d_volume_color = nullptr;

VisualHullType* d_custom_type_visual_hull_tag = nullptr;
uchar* d_visual_hull_tag = nullptr;


// for algebraic reconstruction
std::ofstream gOutFilebRed;
std::ofstream gOutFilebGreen;
std::ofstream gOutFilebBlue;
std::ofstream gOutFileFlameVoxelIndex;
std::ofstream gOutFileARowIndex;
std::ofstream gOutFileARowPointer;
std::ofstream gOutFileAColumnIndex;
std::ofstream gOutFileAValue;
std::ofstream gOutFileRecPixelX;
std::ofstream gOutFileRecPixelY;
std::ofstream gOutFilePerCameraRecPixelSize;

const char* gAlgebraicbRedFile = "b_red.txt";
const char* gAlgebraicbGreenFile = "b_green.txt";
const char* gAlgebraicbBlueFile = "b_blue.txt";
const char* gAlgebraicFlameVoxelIndexFile = "x_flame_voxel_index.txt";
const char* gAlgebraicARowIndexFile = "a_row_index.txt";
const char* gAlgebraicARowPointerFile = "a_row_pointer.txt";
const char* gAlgebraicAColumnIndexFile = "a_column_index.txt";
const char* gAlgebraicAValueFile = "a_value.txt";
const char* gAlgebraicRecPixelXFile = "rec_pixel_x.txt";
const char* gAlgebraicRecPixelYFile = "rec_pixel_y.txt";
const char* gAlgebraicPerCameraRecPixelSizeFile = "per_camera_rec_pixel_size.txt";

const char* gSimulatedSinglePath = "data/simulated/single/";
const char* gAlgebraicSimulatedSinglePath = "data/simulated/single/algebraic/";
const char* gVisualHullImageFile = "visual_hull_img_name.txt";
const char* gAlgebraicNumberFlamePerImageFile = "num_flame_per_image.txt";
const char* gAlgebraicFlamePixelXFilePrefix = "flame_pixel_x_view_";
const char* gAlgebraicFlamePixelYFilePrefix = "flame_pixel_y_view_";
const char* gAlgebraicFlamePixelRedFilePrefix = "flame_pixel_red_view_";
const char* gAlgebraicFlamePixelGreenFilePrefix = "flame_pixel_green_view_";
const char* gAlgebraicFlamePixelBlueFilePrefix = "flame_pixel_blue_view_";
const char* gAlgebraicADimesionFile = "a_dim.txt";


unsigned int gFlameVoxelSize;
unsigned int* d_flame_voxel_index = nullptr;

uint gAnnz = 0;
uint gAm = 0;

std::ofstream evaluationOutput;
